#include <sys/types.h>
#include <sys/socket.h>
//#include <sys/un.h>
//#include <dirent.h>
//#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
//#include <signal.h>
#include <unistd.h>
#include <netdb.h>
//#include <sys/un.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <sstream>
#include "Debug.h"
#include "MemConnection.h"
using namespace panda;
using namespace std;

string MemConnection::get_localhost_ip(char *eth)
{
        int   fd;
        struct  ifreq   ifr;
        struct   sockaddr_in*   sin;
        string sip;
        fd   =   socket(PF_INET,   SOCK_DGRAM,   0);
        memset(&ifr,   0x00,   sizeof(ifr));
        strcpy(ifr.ifr_name,  eth);
        ioctl(fd,  SIOCGIFADDR,   &ifr);
        close(fd);
        sin   =   (struct   sockaddr_in*   )&ifr.ifr_addr;
        sip = (char *)inet_ntoa(sin->sin_addr);
        DEBUG3(sip.c_str(),"; length=", sip.length()); 
        if(sip.compare("0.0.0.0") == 0)
                sip = "127.0.0.1";
        DEBUG4(eth, " : ", sip.c_str(), " assert not 0.0.0.0");
        return sip;
}

bool MemConnection::Connect( )
{
        m_lCurtime = time(NULL);
	if(m_pMemc == NULL )
	{
                DEBUG1("m_pMemc == NULL, so create and Connect!");
		m_pMemc = memcached_create(NULL);
		memcached_return rc = MEMCACHED_SUCCESS;
		if(m_sHostIP.length() <= 0)
		{
			if(m_sHostname.compare("localhost")==0)
			{
				m_sHostIP = get_localhost_ip((char *)"eth0");
				string sip = get_localhost_ip((char *)"eth1");
				if(sip.compare("127.0.0.1") != 0)
					m_sHostIP = sip;
				DEBUG2("localhost ip = ", m_sHostIP.c_str());
			}
			else
			{
				struct hostent *in = NULL;
				in = gethostbyname( m_sHostname.c_str());
				if(NULL != in)
					m_sHostIP =  inet_ntoa(*(struct in_addr *) in->h_addr);
			}
			DEBUG6("get ip by ", m_sHostname, " for : ", m_iPort, " = " , m_sHostIP);
		}
		rc = memcached_server_add(m_pMemc,(char *) m_sHostname.c_str(),(unsigned int) m_iPort);
		if (rc != MEMCACHED_SUCCESS){
			perror("Connect to memcache server");
			memcached_free( m_pMemc );
			m_pMemc  = NULL;
			m_lLasttime = time(NULL);
			m_bLive = false;
		}
		else
		{
                        DEBUG1("create memcached connection success !!!" );
			m_bLive = true;
			char localhost[128];
			gethostname(localhost, 128);
			if ( m_sHostname.compare("localhost") != 0 && m_sHostname.compare(localhost)!=0)
			{
				memcached_behavior_set(m_pMemc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1);
				memcached_behavior_set(m_pMemc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, 50);
				memcached_behavior_set(m_pMemc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 0);
			} 
		}
	}
	else
	{
		cout<<"Needn't conection!!!!"<<endl;
		m_bLive = true;
	}
	return m_bLive;
}
void MemConnection:: Print()
{
	cout<<"service = "<< m_sHostname.c_str()<<endl;;
	cout<<"port = "<< m_iPort<<"\n";
	cout<<"last = "<< m_lLasttime<<"\n";
	m_bLive ? cout<<"bLive = true\n" : cout<< "bLive = false\n";
	cout<<"key = "<< m_iKey << "\n";
	cout<<"backup = "<< m_iBackup << endl;
} 
void MemConnection:: disConnect()
{
        DEBUG1(" ----------- ");
	if(m_pMemc != NULL)
	{
		cout<<" close/free memcached : "<< m_sHostname.c_str()<<":"<<m_iPort <<endl;
		memcached_quit(m_pMemc);
		memcached_free(m_pMemc );
		m_pMemc  = NULL;
		m_lLasttime = time(NULL);
		m_bLive = false;
	}
	else
		m_bLive = false;
}

int MemConnection:: Incr(const char *data, unsigned dlen, const char *prefix, char **buf, unsigned &wsize, unsigned &retv)
{
        uint64_t dval = 0;
        unsigned klen = 0;
        unsigned int incr = 0;
	memcached_return rc; 
        unsigned uint_len = sizeof(unsigned);
        bcopy(data, &klen, uint_len);
        if(dlen < klen + uint_len*2 || klen > PANDA_MC_KEY_MAX  )
        {
              DEBUG4("data length is too small, klen=", klen, "; dlen=", dlen);
              return PANDA_ERR_INPUT_DATA;
        }
  
        char *k = (char *) data + uint_len;
	bcopy(data + uint_len + klen, &incr, uint_len);
        if(incr <= 0)
        {
              DEBUG1("incr <= 0");
              return PANDA_ERR_INPUT_DATA;
        }
        
	if(prefix != NULL && strlen(prefix) > 0)
	{
		char *nk = g_strndup(k, klen);
		ostringstream os;
		os << prefix<< nk;
		g_free(nk);
		rc = memcached_increment(m_pMemc, os.str().c_str(), os.str().length(),incr, &dval);
		DEBUG3( memcached_strerror(m_pMemc, rc)," = rc = ", rc);
		if(rc == 25)  //  MEMCACHED_SERVER_ERROR)
		{
			disConnect();
			Connect();
			if(m_bLive)
				rc = memcached_increment(m_pMemc, os.str().c_str(), os.str().length() , incr, &dval);
		}
	}
	else
        {
                DEBUG4("key = ", k, "; incr's value = ", incr);
		rc = memcached_increment(m_pMemc, k, klen, incr, &dval);
		DEBUG5( memcached_strerror(m_pMemc, rc)," = rc = ", rc, "; dval=",dval);
		if(rc == 25)  //  MEMCACHED_SERVER_ERROR)
		{
			disConnect();
			Connect();
			if(m_bLive)
				rc = memcached_increment(m_pMemc, k, klen, incr, &dval);
		}
	}

	if (rc == MEMCACHED_SUCCESS){
		DEBUG2("Incr success ! key = ", k);
     // length + retcode + value
		retv = 3*uint_len; 
                retv += klen;
		retv += sizeof(uint64_t);
		if(retv > PANDA_MC_VALUE_MAX )
		{     
 			ERRO<<"too big data: length > PANDA_MC_VALUE_MAX"<<endl;
                        wsize = retv = 0;
			return PANDA_ERR_SYSTEM;
		}  
		if(wsize < retv)
		{     
			*buf = (char *)g_realloc(*buf, retv +1);
			if(*buf == NULL){
 				ERRO<<"can't malloc for write buffer !"<<endl;
                                wsize = retv = 0;
				return PANDA_ERR_SYSTEM;
			} 
			wsize = retv+1;                    
		}  
		unsigned usedlen = 0;
                int retcode = 0;
		bcopy(&retv, *buf, uint_len);        //str_length
		usedlen += uint_len;
		bcopy(&retcode, *buf + usedlen, uint_len);   // retcode
                usedlen +=  uint_len;
		bcopy(&dval, *buf + usedlen, sizeof(uint64_t));   // value

		return PANDA_MC_OK;
	}
        else if( rc == 16) // NOT FOUND
        {
              DEBUG3(memcached_strerror(m_pMemc, rc),"=", rc);
	      return PANDA_MC_NOT_FOUND;
        }
        else if(rc==MEMCACHED_ERRNO || rc == 25) //MEMCACHED_SERVER_ERROR )
	{
		DEBUG2(memcached_strerror(m_pMemc, rc), k);
                DEBUG6(memcached_strerror(m_pMemc, rc),"=", rc, "; rc=",rc, "(assert=25); SET bLive = false");
		m_bLive = false;
		m_lLasttime = m_lCurtime;   // time(NULL);
		return PANDA_MC_DOWN;
	}
	else
	{
		DEBUG2(memcached_strerror(m_pMemc, rc), rc);
		return PANDA_MC_FAIL;
	}
}

int MemConnection:: Decr(const char *data, unsigned dlen,const char *prefix, char **buf, unsigned &wsize, unsigned &retv )
{
        uint64_t dval = 0;
        unsigned klen = 0;
        unsigned int incr = 0;
	memcached_return rc; 
        unsigned uint_len = sizeof(unsigned);
        bcopy(data, &klen, uint_len);
        if(dlen < klen + uint_len*2  || klen > PANDA_MC_KEY_MAX )
        {
              DEBUG4("data length is too small, klen=", klen, "; dlen=", dlen);
              return PANDA_ERR_INPUT_DATA;
        }
  
        char *k = (char *) data + uint_len;
	bcopy(data + uint_len + klen, &incr, uint_len);
        if(incr <= 0)
        {
              DEBUG1("decr value <= 0");
              return PANDA_ERR_INPUT_DATA;
        }
        
	if(prefix != NULL && strlen(prefix) > 0)
	{
		char *nk = g_strndup(k, klen);
		ostringstream os;
		os << prefix<< nk;
		g_free(nk);
		rc = memcached_decrement(m_pMemc, os.str().c_str(), os.str().length(),incr, &dval);
		DEBUG5( memcached_strerror(m_pMemc, rc)," = rc = ", rc, "; result = ",dval);
		if(rc == 25)  //  MEMCACHED_SERVER_ERROR)
		{
			disConnect();
			Connect();
			if(m_bLive)
				rc = memcached_decrement(m_pMemc, os.str().c_str(), os.str().length() , incr, &dval);
		}
	}
	else
        {
		rc = memcached_decrement(m_pMemc, k, klen, incr, &dval);
		DEBUG5( memcached_strerror(m_pMemc, rc)," = rc = ", rc,"; result=", dval);
		if(rc == 25)  //  MEMCACHED_SERVER_ERROR)
		{
			disConnect();
			Connect();
			if(m_bLive)
				rc = memcached_decrement(m_pMemc, k, klen, incr, &dval);
		}
	}

	if (rc == MEMCACHED_SUCCESS){
		DEBUG2("Decr cache success ! key = ", k);

		retv = sizeof(int);
		retv += sizeof(unsigned int);
		retv += sizeof(uint64_t);

		if( retv > PANDA_MC_VALUE_MAX )
		{     
			ERRO<<"too big value length > PANDA_MC_VALUE_MAX "<<endl;
			wsize = retv = 0;
			return PANDA_ERR_SYSTEM;
		}  
	
		if(wsize < retv)
		{     
			*buf = (char *)g_realloc(*buf, retv +1);
			if(*buf == NULL){
				ERRO<<"can't malloc for write buffer !"<<endl;
                                wsize = retv = 0;
				return PANDA_ERR_SYSTEM;
			} 
			wsize = retv+1;                    
		}  
	
		unsigned usedlen = 0;
                int retcode = 0;
		bcopy(&retv, *buf, sizeof(unsigned int));            //str_length
		usedlen += sizeof(unsigned int);
		bcopy(&retcode, *buf + usedlen, sizeof(int));   // retcode
                usedlen += sizeof(int);
		bcopy(&dval, *buf + usedlen, sizeof(uint64_t));   // value
                
		return PANDA_MC_OK;
	}
        else if(rc ==  16) // NOT FOUND
        {
              DEBUG3(memcached_strerror(m_pMemc, rc),"=", rc);
	      return PANDA_MC_NOT_FOUND;
        }
	else if(rc==MEMCACHED_ERRNO || rc== 25) //MEMCACHED_SERVER_ERROR )
	{
		DEBUG2(memcached_strerror(m_pMemc, rc), k);
		DEBUG6(memcached_strerror(m_pMemc, rc),"=", rc, "; rc=",rc, "(assert=25); SET bLive = false");
		m_bLive = false;
		m_lLasttime =  m_lCurtime; // time(NULL);
		return PANDA_MC_DOWN;
	}
	else
	{
		DEBUG2(memcached_strerror(m_pMemc, rc), rc);
		return PANDA_MC_FAIL;
	}
}

int MemConnection:: Set(const char *k, unsigned int klen, const char *v, unsigned int vlen, long expire )
{
        DEBUG8("klen=",klen,"; k=",k,"; vlen=",vlen,"; v=",v);
	memcached_return rc = memcached_set(m_pMemc,k, klen, v, vlen, expire, 0);
        DEBUG3( memcached_strerror(m_pMemc, rc)," = rc = ", rc);
       if(rc == 25) //MEMCACHED_SERVER_ERROR)
        {
                disConnect();
                Connect();
		if(m_bLive)
			rc = memcached_set(m_pMemc,k, klen, v, vlen, expire, 0);
	}

	if (rc == MEMCACHED_SUCCESS){
		DEBUG2("set to cache success ! key = ", k);
		return PANDA_MC_OK;
	}
	else if(rc==MEMCACHED_ERRNO || rc== 25) // MEMCACHED_SERVER_ERROR)
	{
		DEBUG2(memcached_strerror(m_pMemc, rc), k);
                DEBUG6(memcached_strerror(m_pMemc, rc),"=", rc, "; rc=",rc,"(assert=25); SET bLive = false");
		m_bLive = false;
		m_lLasttime = m_lCurtime;  // time(NULL);
		return PANDA_MC_DOWN;
	}
	else
	{
		DEBUG2(memcached_strerror(m_pMemc, rc), rc);
		return PANDA_MC_FAIL;
	}
}

int MemConnection :: Get( const char *data, unsigned int dlen, const char *prefix, char **buf, unsigned &wsize, unsigned &vl) 
{
	memcached_return rc;
	uint32_t flag;
	size_t vlen;

        unsigned klen = 0;
        bcopy(data, &klen, sizeof(unsigned));
        if(dlen < klen + sizeof(unsigned) || klen > PANDA_MC_KEY_MAX )
        {
              DEBUG4("data length is too small, klen=", klen, "; dlen=", dlen);
              return PANDA_ERR_INPUT_DATA;
        }
        char *k = (char *) data + sizeof(unsigned);
        char *retval = NULL;
	if(prefix != NULL  && strlen(prefix) > 0)
	{
                ostringstream os;
                char *nk = g_strndup(k, klen);
                os <<prefix<< nk;
                g_free(nk);
                DEBUG2("key = ", os.str().c_str());
		retval = memcached_get(m_pMemc, os.str().c_str(), os.str().length(), &vlen, &flag, &rc);
		DEBUG3( memcached_strerror(m_pMemc, rc)," = rc = ", rc);

		if(rc == 25) // MEMCACHED_SERVER_ERROR)
		{
			disConnect();
			Connect();
			if(m_bLive)
				retval = memcached_get(m_pMemc, os.str().c_str(), os.str().length(), &vlen, &flag, &rc);
		}
	}     
        else
	{
		DEBUG4("key = ", k, "; klen=", klen);
		retval = memcached_get(m_pMemc, k, klen, &vlen, &flag, &rc);
		DEBUG3( memcached_strerror(m_pMemc, rc)," = rc = ", rc);

		if(rc == 25) // MEMCACHED_SERVER_ERROR)
		{
			disConnect();
			Connect();
			if(m_bLive)
				retval = memcached_get(m_pMemc, k, klen, &vlen, &flag, &rc);
		}
	}
	if (rc == MEMCACHED_SUCCESS){
		if (retval != NULL){
			DEBUG2("get result = ", retval);
 	               unsigned items = 1;
		       unsigned uint_len = sizeof(unsigned);
		       vl = uint_len * 5 + klen + vlen; 

		       if( vl > PANDA_MC_VALUE_MAX )
		       {
			       ERRO<<"too big data: length > PANDA_MC_VALUE_MAX !"<<endl;
			       wsize = vl = 0;
			       return PANDA_ERR_SYSTEM;
		       }

		       if(wsize < vl)
		       {
			       DEBUG2("g_realloc(*buf, vl+1) = ", vl+1 );
			       *buf = (char *)g_realloc(*buf, vl +1);
			       if(*buf == NULL){
				       ERRO<<"can't malloc for write buffer !"<<endl;
                                       wsize = vl = 0;
				       return PANDA_ERR_SYSTEM;
			       }
			       wsize = vl + 1;
		       }

		        unsigned usedlen = 0;
                        int retcode = 0;
                        usedlen += uint_len;                            // retcode 
			bcopy(&retcode, *buf + usedlen, sizeof(int));   // retcode
                        usedlen += sizeof(int);                         // items
			bcopy(&items, *buf + usedlen, uint_len);        // items
                        usedlen += uint_len;                            // klen
			bcopy(&klen, *buf + usedlen, uint_len);         // klen
			usedlen += uint_len;                        // k
			bcopy(k, *buf + usedlen, klen);             // k
			usedlen += klen;                            // vlen
			bcopy(&vlen, *buf + usedlen, uint_len);     // vlen
			usedlen += uint_len;                        //v  
			bcopy(retval, *buf + usedlen, vlen);        //v 
			usedlen += vlen;                            //str_length
        		bcopy(&usedlen, *buf, uint_len);            //str_length
			free(retval);
		        vl = usedlen ;
                        DEBUG6("vlen=",vlen,"; alllen = ",usedlen, "; vl=",vl);     
			return PANDA_MC_OK;
		}
		else
		{
                        vl = 0;
			return PANDA_MC_NOT_FOUND;
		}
	}
        else if(rc==MEMCACHED_UNKNOWN_READ_FAILURE || rc==MEMCACHED_ERRNO || rc== 25) // MEMCACHED_SERVER_ERROR )
	{
		m_bLive = false;
		m_lLasttime = m_lCurtime;  //time(NULL);
                DEBUG6(memcached_strerror(m_pMemc, rc),"=", rc, "; rc=",rc, "(assert=25); SET bLive = false");
		return PANDA_MC_DOWN;
	}
	else if( rc == 16) // NOT FOUND
	{
		DEBUG2(memcached_strerror(m_pMemc, rc), rc);
		return PANDA_MC_NOT_FOUND;
	}
        else
	{
		DEBUG2(memcached_strerror(m_pMemc, rc), rc);
		return PANDA_MC_FAIL;
	}
}

int MemConnection :: Delete(const char *k, unsigned int klen) 
{
	memcached_return rc;
        DEBUG2("Delete key = ", k);
	rc= memcached_delete( m_pMemc, k, klen, (time_t)0);
	DEBUG3( memcached_strerror(m_pMemc, rc)," = rc = ", rc);

	if(rc == 25) // MEMCACHED_SERVER_ERROR)
	{
		disConnect();
		Connect();
		if(m_bLive)
			rc= memcached_delete( m_pMemc, k, klen, (time_t)0);
	}

	if (rc == MEMCACHED_SUCCESS){
			return PANDA_MC_OK;
	}
	else if(rc==MEMCACHED_ERRNO || rc == 25) //MEMCACHED_SERVER_ERROR)
	{
		m_bLive = false;
		m_lLasttime = m_lCurtime;  //time(NULL);
		DEBUG6(memcached_strerror(m_pMemc, rc),"=",rc, "; rc=",rc, "(assert=25); SET bLive = false");
		return PANDA_MC_DOWN;
	}
	else
	{
		DEBUG2(memcached_strerror(m_pMemc, rc), rc);
		return PANDA_MC_FAIL;
	}
}


int MemConnection :: MGet(const char *data, unsigned int dlen, int argc, const char *prefix, char **wbuf, unsigned &wsize, unsigned &wbytes) 
//GHashTable *gkey, char **gval, unsigned &gvlen)
{

        memcached_return rc;
        char *keys[argc + 1 ];
        size_t key_length[argc +1];
        int i = 0;
	unsigned usedlen = 0;
	unsigned uint_len = sizeof(unsigned);
        GHashTable *h = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);

        if(prefix != NULL && strlen(prefix) > 0)
	for(i=0; i< argc; i++)
	{
		int ik = 0;
		bcopy(data+usedlen , &ik, uint_len);
		usedlen += uint_len;
		if( usedlen + ik > dlen || ik > PANDA_MC_KEY_MAX )
		{
                        DEBUG1("usedlen+ik > dlen || ik > PANDA_MC_KEY_MAX");
                        g_hash_table_destroy(h);
                     	return PANDA_ERR_INPUT_DATA;
                }
                ostringstream os;
                char *nk = (char *)g_strndup(data+usedlen, ik);
                keys[i] = g_strdup_printf("%s%s", prefix, nk); 
                g_free(nk); 
		DEBUG6("key[", i, "] = ", (char *)keys[i], "; length=", ik);
		key_length[i] = ik;
                g_hash_table_insert(h, keys[i], nk);
	}
        else  // no prefix
	for(i=0; i< argc; i++)
	{
		int ik = 0;
		bcopy(data+usedlen , &ik, uint_len);
		usedlen += uint_len;
		if( usedlen + ik > dlen || ik > PANDA_MC_KEY_MAX )
		{
                        DEBUG1("usedlen+ik > dlen || ik > PANDA_MC_KEY_MAX");
			g_hash_table_destroy(h);
			return PANDA_ERR_INPUT_DATA;
		}
		keys[i] = (char *)data + usedlen;
                usedlen += ik;
		DEBUG6("key[", i, "] = ", (char *)keys[i], "; length=", ik);
		key_length[i] = ik;
	}

        usedlen = 0;
        unsigned items = 0;
        memcached_result_st results_obj;
        memcached_result_st *results;
        rc = memcached_mget(m_pMemc, keys, key_length, argc );
        DEBUG5( memcached_strerror(m_pMemc, rc)," = rc = ", rc, "; MEMCACHED_SERVER_ERROR = ", MEMCACHED_SERVER_ERROR); 
        if(rc == 25) // MEMCACHED_SERVER_ERROR)
        {
                disConnect();
                Connect();
		if(m_bLive)
			rc = memcached_mget(m_pMemc, keys, key_length, argc );
        }

	if(rc == MEMCACHED_SUCCESS) {
		int retcode = 0;
		usedlen = uint_len;                              // retcode 
		bcopy(&retcode, *wbuf + usedlen, sizeof(int));   // retcode
         	usedlen += sizeof(int );                          // items 
                usedlen += uint_len;                             // key

        results= memcached_result_create(m_pMemc, &results_obj);
        while((results= memcached_fetch_result(m_pMemc, &results_obj, &rc)) != NULL )
        {
                if(rc == MEMCACHED_SUCCESS)
		{
			char *pmkey = memcached_result_key_value(results);
			DEBUG2("memcached_result_key_value = ", pmkey);
                        char *pval = NULL;
			if(g_hash_table_size(h) > 0)
				pval = (char *)g_hash_table_lookup(h, pmkey);
			else
				pval = pmkey;
			if(NULL != pval)
			{  
				unsigned ik = strlen((char *)pval);
				unsigned iv = 0;
				char *pMval = memcached_result_value(results);
				// 此处怀疑不能正确处理binary数据的长度！！
				iv = memcached_result_length(results);
                                unsigned need = usedlen + ik + iv + 2*uint_len;
                                DEBUG4("need=", need, "; wsize = ", wsize);
				if( need > wsize)
				{
					if(need > PANDA_MC_KEY_MAX ){
                                                ERRO<<"data is too big, can't malloc such buffer" << endl;
						wsize = 0;
						wbytes = 0;
						rc = MEMCACHED_SOME_ERRORS; 
						break;
					}           
                                        wsize = need * 2  ;   
					*wbuf = (char *)g_realloc(*wbuf, wsize); 
                                        if(*wbuf == NULL){
                                              wsize = 0;
                                              wbytes = 0;
                                              rc = MEMCACHED_SOME_ERRORS; // PANDA_ERR_SYSTEM;
                                              break;
                                         }                                             
				}                         

				bcopy(&ik, *wbuf + usedlen, uint_len);   // klen 
				usedlen += uint_len;                     // kval offset  
				bcopy(pval, *wbuf + usedlen, ik);        // kval
				usedlen += ik;                           // 
				bcopy(&iv, *wbuf + usedlen, uint_len);   // vlen
				usedlen += uint_len;                     //
				bcopy(pMval, *wbuf + usedlen, iv);       // val
				usedlen += iv; 
                                items ++;
                                DEBUG3((char *)pval, "=",  pMval);
			}
                        else
                           DEBUG2("no key =", pmkey );
                }
                else
                  break;
        }
        memcached_result_free(&results_obj);
        }

        g_hash_table_destroy(h); 
	if(rc == 21) // == MEMCACHED_END
	{
		DEBUG3(memcached_strerror(m_pMemc, rc),"; error_code = ", rc);
		if(items > 0)
		{
			bcopy(&usedlen, *wbuf, uint_len);            //str_length
			bcopy(&items, *wbuf + uint_len + sizeof(int), uint_len);  // items
			wbytes = usedlen;
			DEBUG4("items = ", items, "; length=", usedlen); 
			return PANDA_MC_OK;
		}
		else
                {
                        wbytes = 0;
			return PANDA_MC_NOT_FOUND; 
                }
	}
	else if (rc == MEMCACHED_SUCCESS)
        {  // never go here !!
      		bcopy(&usedlen, *wbuf, uint_len);            //str_length
		bcopy(&items, *wbuf + uint_len + sizeof(int), uint_len);        // items
                wbytes = usedlen;
		return PANDA_MC_OK;
	}
        else if(rc==MEMCACHED_UNKNOWN_READ_FAILURE || rc==MEMCACHED_ERRNO ||rc==25) //MEMCACHED_SERVER_ERROR )
	{
		m_bLive = false;
		m_lLasttime = m_lCurtime;  // time(NULL);
		DEBUG6(memcached_strerror(m_pMemc, rc),"=", rc, "; rc=",rc, "(assert=25); SET bLive = false");
		return PANDA_MC_NEXT;
	}
        else if( rc == 16) {
		DEBUG3(memcached_strerror(m_pMemc, rc),"; error_code = ", rc);
		return PANDA_MC_NOT_FOUND;
        }
        else
	{
		DEBUG3(memcached_strerror(m_pMemc, rc),"; error_code = ", rc);
		return PANDA_MC_FAIL;
	}
}

int MemConnection::getStatus()
{
	m_lCurtime = time(NULL);
	int ilive = PANDA_MC_LIVE; // -1 reconnect   0 OK   1 dead, but needn't reconnect
	if(!m_bLive)
	{     
		if(m_lLasttime < ( m_lCurtime - DEAD_CHECK_TIME))
			ilive = PANDA_MC_RESTART;
		else
			ilive = PANDA_MC_NEXT;
	}
	return ilive;
}

